Skip to content

optee-utee-sys,optee-teec-sys: generate the FFI bindings instead of maintaining them by hand - #339

Merged
ivila merged 5 commits into
apache:mainfrom
ivila:opt/generated_sys
Nov 12, 2026
Merged

ivila merged 5 commits into
apache:mainfrom
ivila:opt/generated_sys

Conversation

@ivila

@ivila ivila commented Nov 12, 2026

Copy link
Copy Markdown
Contributor

The FFI was maintained by hand in two places, and both had drifted. None of
these mistakes are caught by the compiler or by the tests: they just make a TA
misbehave at run time.

In optee-utee-sys / optee-teec-sys:

  • The deprecated algorithm constants kept hand-copied values that no longer
    match the headers: TEE_ALG_ECDSA_P192 was 0x70001041 while the header now
    aliases it to TEE_ALG_ECDSA_SHA1 (0x70001042), and the same for
    TEE_ALG_ECDH_P*.
  • Constants were missing outright as upstream grew.

In optee-utee itself (the safe wrapper), the copied values were wrong too:

  • TaInstanceKeepCrashed used gpd.ta.instanceKeepCrashed, but the header and
    the TA runtime use optee.ta.instanceKeepCrashed, so the key never matched.
  • The TEE_PROPSET_TEE_IMPLEMENTATION key set did not match what OP-TEE
    serves: gpd.tee.sockets.version and gpd.tee.sockets.tcp.version were
    missing, while ten keys OP-TEE never implements
    (gpd.tee.cryptography.nist, gpd.tee.trustedStorage.*.rollbackProtection,
    gpd.tee.event.maxSources, …) were exposed and could only return
    TEE_ERROR_ITEM_NOT_FOUND.
  • AttributeId named a constant that does not exist upstream
    (RsaOaepMgf1Hash) and lacked the newer ones (TEE_ATTR_BIT_PROTECTED,
    TEE_ATTR_BIT_VALUE).

Fixing these one at a time only moves the problem to the next OP-TEE bump, so
this takes the declarations out of human hands instead: generate them from the
pinned headers, commit the result, and let CI check it.

What this changes

  • New root xtask with generate-bindings (utee|teec|all). It runs bindgen
    against the TA dev kit (TA_DEV_KIT_DIR) or the client export
    (OPTEE_CLIENT_EXPORT) of the release pinned in optee-version.txt, and
    rewrites crates/optee-{utee,teec}-sys/src/generated.rs.
  • The committed output is plain Rust: ordinary builds need neither libclang nor
    OP-TEE headers. Only the few items bindgen cannot express (property-set
    handles, parameter macros, the TA entry trampoline) stay hand-written in
    handwritten.rs.
  • optee-utee stops carrying literals: the property keys now use the generated
    TA_PROP_STR_* constants, and the attribute, storage, usage, data and handle
    ids come from the bindings, so a wrong value can no longer be typed in by
    hand. Consumers also follow the generated names and Option callbacks.
  • The *-systest crates are removed. A CI job rebuilds the dev kit and the
    client export, re-generates both files and fails on any diff, which replaces
    that coverage. docs/release-tips.md gains the same step.

`generate-bindings (utee|teec|all)` runs bindgen against the TA dev kit
or the client headers and writes the committed `generated.rs`.
`license_header.txt` moves to the repository root so the generator and
`optee-utee-build` share it, and `Cargo.lock` is committed so the output
stays reproducible.
Replace the hand-written declarations with the bindgen output and the
few items bindgen cannot express: the property-set handles, the
parameter macros and the entry trampoline.

`optee-utee` and `optee-utee-build` follow the generated type names,
check the `Option` socket callbacks before calling them, and publish the
generated property table.

`optee-utee-systest` goes away with the hand-written declarations it
checked.
`define_property_key!` now takes a NUL-terminated `&CStr` and prefers the
generated `TA_PROP_STR_*` constants, and `AttributeId`,
`ObjectStorageConstants`, `MiscellaneousConstants` plus the data, usage
and handle flags read their values from `optee-utee-sys`.

`ObjectStorageConstants::IllegalValue` keeps its literal: OP-TEE has no
macro for it.
Replace the hand-written client declarations with the bindgen output.
`optee-teec`, `optee-teec-macros` and `optee-teec-build` follow the
generated names and the `Option` callback fields.

`optee-teec-systest` goes away with the hand-written declarations it
checked, and the documentation that describes the two systest crates is
removed.
Add a job that rebuilds the dev kit and the client export from
`optee-version.txt`, runs `generate-bindings all`, and fails when the
committed `generated.rs` files change. It replaces the ABI coverage
that went away with the `*-systest` crates.

The release checklist gains the same regeneration step plus the manual
property-key pass.
@ivila ivila added the bug Something isn't working label Nov 12, 2026
@ivila ivila changed the title opteeutee-sys,optee-teec-sys: generate the FFI bindings instead of maintaining them by hand optee-utee-sys,optee-teec-sys: generate the FFI bindings instead of maintaining them by hand Nov 12, 2026
@ivila
ivila merged commit 8d040dd into apache:main Nov 12, 2026
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant